<?php 
namespace common\service;

use common\model\sell66\User;
use common\model\sell66\UserBank;
use common\model\sell66\UserOrder;
use common\model\sell66\UserOrderDetail;
use common\model\sell66\UserSteam;
use think\Cache;
use common\model\sell66\UserBalance;
use common\libs\Curl;
use common\libs\StringHelper;
use common\bot\LoginService;
use common\model\sell66\Bot;
use common\bot\SteamBotService;
use common\service\BotInvService;
use common\service\OutTradeService;
use common\model\sell66\OutTrade;

class TradeOfferService{

	public static $instance = null;
	const ASK_ITEMS = 1; //机器人索要
	const FOR_ITEMS = 2; //机器人给予
	
	private function __construct(){
	}

	public static function getInstance(){
		if(self::$instance == null){
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	public function sendOkMessage($type,$to,$content){
		$url = getenv('socket_address');
		if(empty($url)){
			$url = "http://47.93.245.56:2121/";
		}
		$param = array(
			'type'=>$type,
			'to'=>$to,
			'content'=>$content
		);
		return Curl::http_post($url, $param);
	}

	public function getDoingOrders($userId)
    {
        return UserOrder::doingOrders($userId);
    }
	
	public function lastCreatingOrder($userId){
		$order = UserOrder::getUserTradingOrder($userId);
		if(empty($order)){
			return false;
		}
		return  [
			'orderId'=>$order['user_order_id'],
			'orderNo'=>$order['orderno'],
			'currency'=>$order['currency'],
			'tradeofferId'=>$order['tradeoffer_id'],
			'price'=>$order['price'],
			'note'=>$order['tradeoffer'],
			'withdrawNo'=>$order['withdraw_no'],
			'createdTime'=>$order['created_time'],
			'expireTime'=>$order['expire_time'],
			'leftTime'=>$order['expire_time']-time()
		];
	}

	/**
	 * 检测物品是否可以交易
	 * @param unknown $steamId
	 * @param unknown $items
	 * @return boolean
	 */
	private function checkItems($steamId,$items){
		$userInventory = [];//用户库存 
		$userInventoryTemp = [];
		
		foreach ($items as $item){
			$appId = $item['appId'];
			$cacheKey = sprintf(INVENTORY_KEY_STEAMID_APPID,$steamId,$appId);
			$userAppInventory = Cache::store('redis')->get($cacheKey);
			if(empty($userAppInventory)){
				return false;
			}
			foreach ($userAppInventory as $one){
				$userInventory[$appId][] = $one['positionId'];
				$userInventoryTemp[$appId][] = $one;
			}
		}
		$result = [];
		foreach ($items as $item){
			$itemData = $item['items'];
			$appId = $item['appId'];
			foreach ($itemData as $position){
				if(!in_array($position, $userInventory[$appId])){
					return false;
				}else{
					$result[] =  $userInventoryTemp[$appId];
				}
			}
		}
		var_dump($result);die;
		// TODO check 物品归属
		// TODO check 是否可以回收
		return $result;
	}

    private function getBot($botId){
        $bot = Bot::where('id', $botId)->find();
        $botId = $bot['id'];
        $botAccount = $bot['steam_account'];
        $steam = LoginService::getInstance()->getBot($botAccount);
        return array('botId'=>$botId, 'can_from'=>$bot['can_from'], 'steam'=>$steam);
    }
	
	private function getRandBot($times = 0){
		$bot = Bot::getOneLoginRobot();
        $botId = $bot['id'];
		$botAccount = $bot['steam_account'];
		$steam = LoginService::getInstance()->getBot($botAccount);
		if(empty($steam) && $times < 3){
            $times++;
            return $this->getRandBot($times);
        }

		return array('botId'=>$botId,'steam'=>$steam);
	}
	/**
	 * 
	 * @param unknown $userInfo
	 * @param unknown $Items = ['appId'=>730,'items'=>[1,2,3,4,5]],
	 * @param string $user_bank_id  订单成功后提现方式 
	 * @return multitype:number string |boolean|multitype:number string boolean unknown
	 */
	public function create($userInfo, $Items,$user_bank_id) {
		$appIds = [];
		foreach ($Items as $item){
			if(!in_array($item['appId'], $appIds)){
				$appIds[] = $item['appId'];
			}
		}
		$steamId = $userInfo['steam_id'];
		$userId = $userInfo['user_id'];
        $userVo = User::getUsersByUserId($userId);
        //检测用户是否审核
        if($userVo && $userVo->limit_status == 1){
            return -6;
        }
		if(empty($Items)){
			foreach ($appIds as $appId){
				InvService::getInstance()->resetUserInventoryStatus($steamId, $appId);
			}
			return -2;//['code' => 103, 'msg' => '检测物品数据过程，信息错误了']; 
		}

		//初始化物品数据
        $assentItems = [];
        $quatity = 0;
        $sumPrice = 0;
        $oringePrice = 0;
        $oids = array();
        foreach ($Items as  $inventory) {
            foreach ($inventory['items'] as $one){
                $quatity += 1;
                $sumPrice += $one['plus_price'];
                $oringePrice += $one['price'];
                $one['price'] = number_format($one['plus_price'] / $one['amount'],2,'.','');
                $assentItems[] = $one;
                $oids[] = $one['id'];
            }
        }
        $oids = implode(',', $oids);

        //检测交易链接并筛选机器人
		$steamUser = UserSteam::findBySteamId($steamId);
		$tradeUrl = $steamUser['trade_off_url'];

        $tradeofferStatusInfo = SteamBotService::getInstance()->rpcCheckTradeUrl($tradeUrl, $steamUser['steam_id']);
        if($tradeofferStatusInfo['code'] === false){
            return $tradeofferStatusInfo;
        }

        $botInfo = $tradeofferStatusInfo['botInfo'];
        if (!$botInfo) {
            return -3;
        }

        $canFrom = $botInfo['bot']['can_from'];
        if($canFrom == 2){
            return -4;
        }

        $orderVerifyCode = StringHelper::getRandomCode();
        $tradeMsg = "交易验证码：{$orderVerifyCode},回收价：{$sumPrice} 为确保本次交易安全可靠，请在发起交易的页面验证该单号。若单号不匹配，请拒绝交易。";
        $data['user_id'] = $userInfo['user_id'];
        $data['bot_id'] = 0;
        $data['app_id'] = $appIds[0];
        $data['steam_id'] = $userInfo['steam_id'];
        $data['price'] = $sumPrice;  //成交价格
        $data['origin_price'] = $oringePrice; //未加成价格
        $data['discount_price'] = sprintf('%.2f', number_format($data['price'] - $data['origin_price'],2, '.', '')); //未加成价格
        $data['plus_ratio'] = 0;
        $data['verify_code'] = $orderVerifyCode;
        $data['plus_ratio_info'] = '';
        $data['tradeoffer'] = $tradeMsg;
        $data['tradeoffer_id'] = -1;
        $data['user_bank_id'] = $user_bank_id;
        $data['amount'] = $quatity;
        $data['assent_items'] = $assentItems;

        $userOrderId = UserOrder::createOrder($data);

        if(!$userOrderId){
            return -4;//交易错误
        }

        $result = SteamBotService::getInstance()->rpcSentTrade($appIds[0], $steamId, $tradeUrl, $oids);
        if($result['code'] === false){
            UserOrder::updateUserOrderStatus($userOrderId, 0, -1, -100);
            return $result;
        }

        UserOrder::updateUserOrderByFromTradeId($userOrderId, $result['data']['fromTradeId']);

        foreach ($appIds as $appId){
            InvService::getInstance()->resetUserInventoryStatus($steamId, $appId);
        }
        return ['user_order_id' => $userOrderId];
	}
	
	public function nearRecordInfo(){
		$result = array();
		$finishedOrderCount = UserOrder::getFinishedOrderCount();
		$orderList = UserOrder::getNearFinishedOrders();
		$result['countOrder'] = $finishedOrderCount;
		$result['orders'] = [];
		foreach ($orderList as $order){
			$temp = [];
			$temp['userName'] = isset($order->steam->personaname) ? StringHelper::PassStart($order->steam->personaname,1,1) : '匿名用户';
			$temp['price'] = $order['price'] > 2000 ? '2000+' : $order['price'];
			$temp['finishedTime'] = StringHelper::fomartTime($order['finished_time']);
			$result['orders'][] = $temp;
		}
		return $result;
	}
	
	public function getTradeOrderByNo($userId,$orderNo){
		$order = UserOrder::getOrderByOrderNo($userId,$orderNo);
		if(empty($order)){
			return false;
		}
		return  [
			'orderId'=>$order['user_order_id'],
			'orderNo'=>$order['orderno'],
			'currency'=>$order['currency'],
			'price'=>$order['price'],
			'note'=>$order['tradeoffer'],
			'withdrawNo'=>$order['withdraw_no'],
			'createdTime'=>$order['created_time'],
            'tradeoffer_status' => $order['tradeoffer_status'],
            'order_status' => $order['order_status'],
		];
	}
	
	public function getDetail($userId,$orderNo){
		$order = UserOrder::getOrderByOrderNo($userId, $orderNo);
		if($order['order_status'] != UserOrder::$orderStatusMaps['success']){
			return false;
		}
		if(empty($order)){
			return false;
		}
		
		$orderRes = array(
				'orderId'=>$order['user_order_id'],
				'orderNo'=>$order['orderno'],
				'currency'=>$order['currency'],
				'price'=>$order['price'],
				'createdTime'=>$order['created_time'],
				'finishedTime'=>$order['finished_time']
		);
		$orderItems = [];
		foreach ($order->orderdetails as $item){
			$orderItems[] = $item;
		}
		return array("order"=>$orderRes,'orderItems'=>$orderItems);
	}

	public function sendTrade($userOrderId)
    {
        $orderInfo = UserOrder::where('user_order_id', $userOrderId)->find();
        if(!$orderInfo){
            return ['code'=>false, 'message'=>-4];
        }
        $userInfo = UserSteam::where('user_id', $orderInfo['user_id'])->find();
        if(!$userInfo){
            return ['code'=>false, 'message'=>-4];
        }

        $userId = $userInfo['user_id'];
        $steamId = $userInfo['steam_id'];

        $steam_trade_token = $userInfo['steam_trade_token'];
        $bot = $this->getBot($orderInfo['bot_id']);

        if (!$bot['steam']) {
            return ['code'=>false, 'message'=>-3];
        }

        $botId = $bot['botId'];
        $steam = $bot['steam'];
        if ($steam->isLoggedIn()) {
            $tradeOffers = $steam->tradeOffers();
            $trade = $tradeOffers->createTrade($orderInfo['steam_id']);

            $orderDetail = UserOrderDetail::where('user_order_id', $userOrderId)->select();
            if(!$orderDetail){
                return ['code'=>false, 'message'=>-4];
            }
            foreach ($orderDetail as $one){
                $trade->addOtherItem($one['app_id'], 2, $one['o_id'],$one['amount']);
            }

            $trade->setMessage($orderInfo['tradeoffer']);
            $tradeId = $trade->sendWithToken($steam_trade_token);
            if ($error = $trade->getError()) {
                if(strpos($error,'15') !== false){
                    $error = '【VACBanned】'.$error;
                }
                LogService::getInstance()->addActionLog(__FUNCTION__, $userId, $steamId, $error, array('botId'=>$botId));
            }

            if(empty($tradeId)){
                UserOrder::cannelOrderByOrderId($userId, $userOrderId,false);//取消订单不发送邮件
                return ['code'=>false, 'message'=>-4];
            }
            UserOrder::where(['user_order_id'=>$userOrderId])
                ->update(['tradeoffer_id'=>$tradeId, 'tradeoffer_status'=>UserOrder::$tradeOfferStatusMap['create']]);
            return ['code'=>true, 'data'=>['trade_id' => $tradeId]];
        } else {
            LogService::getInstance()->addActionLog(__FUNCTION__, $userId, $steamId, '机器人登陆失败',array('botId'=>$botId));
            LoginService::getInstance()->addReloginBotQueue($botId);
            return ['code'=>false, 'message'=>-3];//机器人未登录
        }
    }

    public function fromNotice($userId, $userOrderId = NULL)
    {
        $notice = UserOrder::getUserOrderByFromNotice($userId, $userOrderId);
        if ($notice) {
            foreach ($notice as &$item) {
                $item = array(
                    'tradeOfferId' => $item['tradeoffer_id'],
                    'userOrderId' => $item['user_order_id'],
                    'status'  => $item['tradeoffer_status'],
                    'leftTime'=>(time() - $item['created_time']),
                );
            }
        }

        return $notice;
    }

    public function outNotice($userId, $outTradeId = NULL)
    {
        $notice = OutTrade::getOutTradeByOutNotice($userId, $outTradeId);
        if ($notice) {
            foreach ($notice as &$item) {
                $item = array(
                    'tradeOfferId' => $item['tradeoffer_id'],
                    'outTradeId' => $item['out_trade_id'],
                    'status'  => $item['tradeoffer_status'],
                    'leftTime'=>(time() - strtotime($item['created_at'])),
                );
            }
        }

        return $notice;
    }

    public function outTrade($userId, $appId, array $botInvIds)
    {
        if (count($botInvIds) > 200) {
            return -1;
        }

        $count = OutTrade::getOutTradeByReadingTotals($userId);
        if ($count > 0) {
            return -2;
        }

        $userInfo = UserSteam::getUserInfo($userId);
        if (!$userInfo) {
            return -3;
        }

        $checkInvs = BotInvService::getInstance()->checkUserInvs($userId, $appId, $botInvIds);
        if (!$checkInvs) {
            return -4;
        }

        $invs = array();
        $botInvs = BotInvService::getInstance()->getBotInvByUserId($userId, $appId, $botInvIds);
        foreach ($botInvs as $botInv) {
            if ($botInv['cd_time'] > 0) {
                return -5;
            }
            $invs[$botInv['bot_id']][] = $botInv;
        }

        $tradeOfferIds = [];
        foreach ($invs as $botId => $inv) {
            $botTradeId = OutTrade::insertOutTrade($userId, $appId, $botId, $inv);

            $tradeOfferIds[] = array(
                'out_trade_id' => $botTradeId,
                'tradeofferId' => -1,
                'status' => -1,
            );
        }

        return $tradeOfferIds;
    }
}